home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume20 / reactivekbd / part03 < prev    next >
Encoding:
Internet Message Format  |  1989-10-16  |  23.1 KB

  1. Subject:  v20i031:  Command-line editor with predictions, Part03/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Mark James <jamesm@cpsc.UCalgary.CA>
  7. Posting-number: Volume 20, Issue 31
  8. Archive-name: reactivekbd/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 3 (of 4)."
  17. # Contents:  file+rk.c
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'file+rk.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'file+rk.c'\"
  21. else
  22. echo shar: Extracting \"'file+rk.c'\" \(21384 characters\)
  23. sed "s/^X//" >'file+rk.c' <<'END_OF_FILE'
  24. X/* LINTLIBRARY */
  25. X
  26. X#include "file+rk.h"        /* JJD 3-89 */
  27. X#include "rk_button.h"        /* JJD 9-86 */
  28. X#include "functions.h"        /* MLJ 5-89 */
  29. X#include <sys/types.h>
  30. X#include <sys/time.h>
  31. X#include <sys/errno.h>
  32. X#include <sys/stat.h>  
  33. X#include <signal.h>
  34. X#include <sys/wait.h>
  35. X#include <sys/ioctl.h>
  36. X#include <fcntl.h>
  37. X#include <stdio.h>
  38. X#include <sys/file.h>
  39. Xchar           *getenv();
  40. X#include <pwd.h>
  41. X
  42. X/* struct passwd *pwd; */
  43. X
  44. X/* Global Variables */
  45. X
  46. Xextern          errno;
  47. X
  48. Xint             pty_master, pty_slave, tty;
  49. Xstruct sgttyb   new_stdin, old_stdin;
  50. X
  51. Xstruct sgttyb   pty_sgtty;
  52. X
  53. Xchar            tc_ent[1024], tc_seq_buf[1024], *clear_to_eol;
  54. Xchar           *cursor_left, *cursor_right;
  55. Xchar           *enter_insert_mode, *exit_insert_mode;
  56. Xchar           *pre_insert_char, *post_insert_char;
  57. Xchar           *enter_delete_mode, *exit_delete_mode, *delete_a_char;
  58. Xchar           *clear_screen;
  59. Xchar           *enter_standout_mode, *exit_standout_mode;    /* JJD 9-86 */
  60. X
  61. Xchar            pred_buff[MAX_CMD_LINE_LENGTH];    /* JJD 9-86 */
  62. Xchar            pred_on_display = 0;    /* JJD 9-86 */
  63. Xchar            pred_mode = 1;    /* JJD 9-86 */
  64. Xint             pred_number = 0;/* JJD 9-86 */
  65. Xchar        show_eol_mode = 1;
  66. Xchar            nl_truncate_mode = 1;    /* JJD 9-86 */
  67. Xchar            eol_only_mode = 1;    /* JJD 9-86 */
  68. Xchar            eol_longer_mode = 1;    /* JJD 9-86 */
  69. Xchar            lisp_mode = 0;
  70. Xchar        add_space_mode = 0;
  71. Xchar        silent=0;
  72. Xchar        login=1;
  73. X
  74. Xint             (*keymap[128][MAXEXTENSIONS]) ();
  75. Xchar            meta_prefixes[MAXEXTENSIONS][MAXEXTENSIONS];
  76. Xint        meta_map[MAXEXTENSIONS][MAXEXTENSIONS];
  77. Xint        current_key_map=0;
  78. Xchar        next_free_map=1;
  79. Xchar           *shellname;
  80. X
  81. XED_STRUCT       editor_data;
  82. X
  83. Xchar            output_string[1024], temp_str[1024];
  84. Xint             output_string_length;
  85. Xint         finished=0;
  86. Xint        childid;
  87. X
  88. Xint        num_buffers=64;
  89. X
  90. X
  91. Xvoid childdied()
  92. X{
  93. X    union wait      w;
  94. X    register int    pid;
  95. X
  96. X    while ((pid = wait3(&w, WUNTRACED | WNOHANG, 0)) > 0) {
  97. X        if (WIFSTOPPED(w)) {
  98. X            fprintf(stderr,"Stopped.\r\n");
  99. X        } else if (WIFEXITED(w)) {
  100. X        } else if (WIFSIGNALED(w)) {
  101. X            fprintf(stderr,"Killed.\r\n");
  102. X        }
  103. X
  104. X                /* if this is our shell who died, shut down */
  105. X        if(pid==childid){    
  106. X            abortit("\r\n",0);
  107. X        }
  108. X    }
  109. X    return;
  110. X}
  111. X
  112. Xvoid cleanup()
  113. X{
  114. X    abortit("Segmentation fault, aborting...\n",-1);
  115. X}
  116. X
  117. X
  118. X
  119. Xint READ(d, buf, nbytes)
  120. Xint d;
  121. Xchar *buf;
  122. Xint nbytes;
  123. X{
  124. X    int ret;
  125. X    static int count=0;
  126. X    
  127. X    if((ret=read(d,buf,nbytes))<-1){
  128. X        if(errno==EBADF){
  129. X            if(count){
  130. X                perror("Read");
  131. X                abortit("",-1);
  132. X            } else {
  133. X                count++;
  134. X                sleep(1);  /* wait for the signal */
  135. X            }
  136. X        } else {
  137. X            perror("Read");
  138. X            abortit("",-1);
  139. X        }
  140. X    } else {
  141. X        return(ret);
  142. X    }
  143. X}
  144. X
  145. Xmain(argc, argv)
  146. X    int             argc;
  147. X    char          *argv[];
  148. X{
  149. X
  150. X    char           *getenv();    /* JJD 3-89 added */
  151. X    get_termcap_stuff();
  152. X    get_command_line_arguments(argc,argv);
  153. X    set_up_keymap();
  154. X    get_key_bindings(); 
  155. X    init();
  156. X    set_up_buffers();
  157. X    file();
  158. X    /*NOTREACHED*/
  159. X    shutdown_pty_and_tty();
  160. X    shutdown_();
  161. X    abortit("",1);        /* JJD 3-89 added 1 */
  162. X}
  163. X
  164. X
  165. Xget_termcap_stuff()
  166. X{
  167. X
  168. X    char           *termname, *tbuf, *getenv(), *tgetstr();
  169. X
  170. X    termname = getenv("TERM");
  171. X    if (!termname) {
  172. X        enter_insert_mode = exit_insert_mode = pre_insert_char =
  173. X            post_insert_char = 0;
  174. X        enter_delete_mode = exit_delete_mode = delete_a_char = 0;
  175. X        cursor_right = 0;
  176. X        cursor_left = "\010";
  177. X        clear_screen = 0;
  178. X        enter_standout_mode = exit_standout_mode = 0;    /* JJD 9-86 */
  179. X        return;
  180. X    }
  181. X    tbuf = tc_seq_buf;
  182. X    if (tgetent(tc_ent, termname) != 1) {
  183. X        enter_insert_mode = exit_insert_mode = pre_insert_char = 0;
  184. X        post_insert_char = enter_delete_mode = exit_delete_mode = 0;
  185. X        delete_a_char = cursor_right = clear_screen = 0;
  186. X        cursor_left = "\010";
  187. X        enter_standout_mode = exit_standout_mode = 0;    /* JJD 9-86 */
  188. X        return;
  189. X    }
  190. X    if (tgetflag("bs"))
  191. X        cursor_left = "\010";
  192. X    else
  193. X        cursor_left = tgetstr("bc", &tbuf);
  194. X
  195. X    clear_to_eol = tgetstr("ce", &tbuf);
  196. X    cursor_right = tgetstr("nd", &tbuf);
  197. X    enter_insert_mode = tgetstr("im", &tbuf);
  198. X    exit_insert_mode = tgetstr("ei", &tbuf);
  199. X    pre_insert_char = tgetstr("ic", &tbuf);
  200. X    post_insert_char = tgetstr("ip", &tbuf);
  201. X    enter_delete_mode = tgetstr("dm", &tbuf);
  202. X    exit_delete_mode = tgetstr("ed", &tbuf);
  203. X    delete_a_char = tgetstr("dc", &tbuf);
  204. X    clear_screen = tgetstr("cl", &tbuf);
  205. X    enter_standout_mode = tgetstr("so", &tbuf);    /* JJD 9-86 */
  206. X    exit_standout_mode = tgetstr("se", &tbuf);    /* JJD 9-86 */
  207. X
  208. X    if (!enter_standout_mode || !exit_standout_mode)    /* JJD 9-86 */
  209. X        enter_standout_mode = exit_standout_mode = 0;
  210. X
  211. X    if (!enter_delete_mode || !exit_delete_mode)
  212. X        enter_delete_mode = exit_delete_mode = 0;
  213. X
  214. X    if (!enter_insert_mode || !exit_insert_mode)
  215. X        enter_insert_mode = exit_insert_mode = 0;
  216. X}
  217. X
  218. X#define LETTERS "pqr"
  219. X
  220. Xinit()
  221. X{
  222. X    int             i = 48, c = 0;
  223. X    char            buf[100];
  224. X    struct sgttyb   master_sgttyb,slave_sgttyb;
  225. X    int             pid;
  226. X
  227. X
  228. X
  229. X
  230. X    while (--i >= 0) {
  231. X        sprintf(buf, "/dev/pty%c%x", LETTERS[c >> 4], c & 15);
  232. X        if ((pty_master = open(buf, (O_RDWR | O_EXCL))) != -1)
  233. X            break;
  234. X        c++;
  235. X    }
  236. X    if (i <= 0) {
  237. X        printf("Unable to open a pty, aborting...\r\n");
  238. X        abortit("",-1);
  239. X    }
  240. X    ioctl(0, TIOCGETP, &old_stdin);
  241. X    ioctl(0, TIOCGETP, &new_stdin);
  242. X    new_stdin.sg_flags |= (CBREAK|RAW|CRMOD);
  243. X    new_stdin.sg_flags &= ~(ECHO);
  244. X    ioctl(0, TIOCSETP, &new_stdin);
  245. X
  246. X    ioctl(pty_master, TIOCGETP, &master_sgttyb);
  247. X    master_sgttyb.sg_flags &= ~(RAW | CBREAK| LCASE);
  248. X    master_sgttyb.sg_flags |= (ECHO | CRMOD | FF0);
  249. X    master_sgttyb.sg_ospeed = old_stdin.sg_ospeed;
  250. X    master_sgttyb.sg_ispeed = old_stdin.sg_ispeed;
  251. X    ioctl(pty_master, TIOCSETP, &master_sgttyb);
  252. X
  253. X    switch (pid = fork()) {
  254. X    case -1:
  255. X        perror("Fork");
  256. X        abortit("",-1);
  257. X        break;
  258. X    case 0:
  259. X        signal(SIGINT, SIG_DFL);
  260. X        signal(SIGQUIT, SIG_DFL);
  261. X        if ((tty = open("/dev/tty", O_RDWR)) < 0) {
  262. X            perror("/dev/tty");
  263. X            abortit("",-1);
  264. X        }
  265. X        ioctl(tty, TIOCNOTTY, &pid);
  266. X        close(tty);
  267. X        close(pty_master);
  268. X        close(0);
  269. X        sprintf(buf, "/dev/tty%c%x", LETTERS[c >> 4], c & 15);
  270. X        if ((pty_slave = open(buf, (O_RDWR | O_EXCL))) < 0) {
  271. X            perror(buf);
  272. X            abortit("",-1);
  273. X        }
  274. X        dup2(0, 1);
  275. X        dup2(0, 2);
  276. X        ioctl(0, TIOCGETP, &slave_sgttyb);
  277. X        slave_sgttyb.sg_flags &= ~(RAW | CBREAK| LCASE);
  278. X        slave_sgttyb.sg_flags |= (ECHO | FF0 | CRMOD );
  279. X        slave_sgttyb.sg_ospeed = old_stdin.sg_ospeed;
  280. X        slave_sgttyb.sg_ispeed = old_stdin.sg_ispeed;
  281. X        ioctl(0, TIOCSETP, &slave_sgttyb);
  282. X        pid = getpid();
  283. X        if (setpgrp(0, pid) < 0) {
  284. X            perror("Setpgrp");
  285. X            abortit("",-1);
  286. X        }
  287. X        ioctl(0, TIOCSPGRP, &pid);
  288. X        shellname = (char *)getenv ("SHELL");
  289. X        if(!shellname)
  290. X            shellname="/bin/csh";
  291. X        if(login){
  292. X            if (execl(shellname, "-", (char *) 0) < 0) {
  293. X                perror("execl");
  294. X                abortit("",-1);
  295. X            }
  296. X        } else {
  297. X            if (execl(shellname, "csh", (char *) 0) < 0) {
  298. X                perror("execl");
  299. X                abortit("",-1);
  300. X            }
  301. X        }
  302. X            
  303. X        break;
  304. X
  305. X    default:childid=pid;
  306. X        break;
  307. X    }
  308. X}
  309. X
  310. Xset_up_buffers()
  311. X{
  312. X
  313. X    int             num_buffs;
  314. X    struct ed_buffs *prev_ptr;
  315. X
  316. X    editor_data.current_ed_buff_ptr =
  317. X        (struct ed_buffs *) malloc(sizeof(struct ed_buffs));
  318. X
  319. X    prev_ptr = editor_data.current_ed_buff_ptr;
  320. X    prev_ptr->dot = prev_ptr->string;
  321. X    prev_ptr->mark = prev_ptr->string;    /* JJD 3-89 added */
  322. X
  323. X    for (num_buffs = num_buffers - 1; num_buffs; --num_buffs) {
  324. X        prev_ptr->next_ptr =
  325. X            (struct ed_buffs *) malloc(sizeof(struct ed_buffs));
  326. X        prev_ptr->next_ptr->prev_ptr = prev_ptr;
  327. X        prev_ptr = prev_ptr->next_ptr;
  328. X        prev_ptr->dot = prev_ptr->string;
  329. X        prev_ptr->mark = prev_ptr->string;    /* JJD 3-89 added */
  330. X        *(prev_ptr->dot) = '\0';
  331. X    }
  332. X
  333. X    prev_ptr->next_ptr = editor_data.current_ed_buff_ptr;
  334. X    editor_data.current_ed_buff_ptr->prev_ptr = prev_ptr;
  335. X
  336. X    editor_data.current_input_char = '\0';
  337. X    editor_data.universal_argument = 1;
  338. X    editor_data.current_buffer = editor_data.current_ed_buff_ptr->string;
  339. X    editor_data.dot = editor_data.current_buffer;
  340. X    /* JJD 3-89 added */
  341. X    editor_data.mark = editor_data.current_ed_buff_ptr->mark;
  342. X    editor_data.current_buffer[0] = '\0';
  343. X    output_string[0] = '\0';
  344. X    output_string_length = 0;
  345. X    temp_str[0] = '\0';
  346. X}
  347. X
  348. X
  349. Xset_up_keymap()
  350. X{
  351. X    int x,y;
  352. X    char buf[4];
  353. X
  354. X    buf[1]=0;
  355. X
  356. X    for(y=0;y<MAXEXTENSIONS;y++){
  357. X        for(x=0;x<MAXEXTENSIONS;x++){
  358. X            meta_prefixes[x][y]=0;
  359. X            meta_map[x][y]=0;
  360. X        }
  361. X    }
  362. X
  363. X    for(y=0;y<MAXEXTENSIONS;y++){
  364. X        for(x=0;x<128;x++){
  365. X            keymap[x][y]=BOGUS;
  366. X        }
  367. X    }
  368. X
  369. X
  370. X
  371. X    bind_to_key("^@",set_mark);/* CTRL-@ or CTRL-sp *//* JJD 3-89 */
  372. X       bind_to_key("^A",beginning_of_line);    /* CTRL-A */
  373. X    bind_to_key("^B",backward_char);    /* CTRL-B */
  374. X    bind_to_key("^C",file_completion);    /* CTRL-C *//* JJD 2-89 */
  375. X    bind_to_key("^D",delete_char);    /* CTRL-D */
  376. X    bind_to_key("^E",end_of_line);    /* CTRL-E */
  377. X    bind_to_key("^F",forward_char);    /* CTRL-F */
  378. X    bind_to_key("^G",backspace_word);    /* CTRL-G *//* JJD 2-89 */
  379. X    bind_to_key("^H",backspace_char);    /* CTRL-H & backspace key */
  380. X    bind_to_key("^I",self_insert);    /* CTRL-I & TAB key       */
  381. X    bind_to_key("^J",finish_editing_line);    /* CTRL-J */
  382. X    bind_to_key("^K",discard_rest_of_line);    /* CTRL-K */
  383. X    bind_to_key("^L",clear_display);    /* CTRL-L */
  384. X    bind_to_key("^M",finish_editing_line);    /* CTRL-M */
  385. X    bind_to_key("^N",next_line);    /* CTRL-N */
  386. X    bind_to_key("^O",previous_pred);    /* CTRL-O *//* JJD 9-86 */
  387. X    bind_to_key("^P",previous_line);    /* CTRL-P */
  388. X    bind_to_key("^Q",accept_forward_char);    /* CTRL-Q *//* JJD 9-86 */
  389. X    bind_to_key("^R",next_pred);    /* CTRL-R *//* JJD 9-86 */
  390. X    bind_to_key("^S",accept_to_end_of_line);    /* CTRL-S *//* JJD 9-86 */
  391. X    bind_to_key("^T",twiddle_chars);    /* CTRL-T */
  392. X    bind_to_key("^U",increment_universal_argument);    /* CTRL-U */
  393. X    bind_to_key("^V",quote_char);    /* CTRL-V *//* JJD 9-86 */
  394. X    bind_to_key("^W",accept_forward_word);    /* CTRL-W *//* JJD 9-86 */
  395. X    bind_to_key("^X",show_mark);    /* CTRL-X *//* JJD 3-89 */
  396. X    bind_to_key("^Y",yank_from_kill_buffer);    /* CTRL-Y */
  397. X    bind_to_key("^Z",insert_suspend_char);    /* CTRL-Z */
  398. X    bind_to_key("^\\",command_completion);    /* CTRL-\ */ 
  399. X    bind_to_key("\035",BOGUS);
  400. X    bind_to_key("^^",insert_stop_char);    /* CTRL-^ *//* JJD 9-86 */
  401. X    bind_to_key("^_",insert_start_char);    /* CTRL-_ *//* JJD 9-86 */
  402. X    for(x=' ';x<'(';x++){
  403. X        buf[0]=x;
  404. X        bind_to_key(buf,self_insert);
  405. X    }
  406. X    bind_to_key("(",open_paren);    /* electric-( *//* Elec-( */
  407. X    bind_to_key(")",close_paren);    /* electric-) *//* Elec-) */
  408. X    for(x='*';x< '\\';x++){
  409. X        buf[0]=x;
  410. X        bind_to_key(buf,self_insert);
  411. X    }
  412. X    bind_to_key("\\\\",self_insert); /* need 4 \'s ! */
  413. X    bind_to_key("]",self_insert);
  414. X    bind_to_key("\\^",self_insert);
  415. X    for(x='_';x<= '~';x++){
  416. X        buf[0]=x;
  417. X        bind_to_key(buf,self_insert);
  418. X    }
  419. X
  420. X    bind_to_key("\177",insert_interrupt_char);    /* DEL key *//* JJD 2-89 */
  421. X    
  422. X
  423. X    bind_to_key("^[^[",discard_current_edit_line);    /* ESC-ESC */
  424. X    bind_to_key("^[ ",toggle_add_space_mode);    /* ESC-space */
  425. X    bind_to_key("^[(",backward_paren);    /* ESC-( */
  426. X    bind_to_key("^[)",forward_paren);    /* ESC-) */
  427. X    bind_to_key("^[-",ul_to_dash_word);    /* ESC--  */
  428. X    bind_to_key("^[=",previous_line);    /* ESC-=  */
  429. X    bind_to_key("^[?",describe_bindings);    /* ESC-?  */
  430. X    bind_to_key("^[E",toggle_eol_only_mode);    /* ESC-E  *//* JJD 9-86 */
  431. X    bind_to_key("^[C",describe_arguments);
  432. X    bind_to_key("^[F",toggle_eol_longer_mode);    /* ESC-F  *//* JJD 9-86 */
  433. X    bind_to_key("^[L",toggle_lisp_mode);    /* ESC-L  */
  434. X    bind_to_key("^[N",toggle_nl_truncate_mode);    /* ESC-N  *//* JJD 9-86 */
  435. X    bind_to_key("^[P",toggle_pred_mode);    /* ESC-P  *//* JJD 9-86 */
  436. X    bind_to_key("^[Q",insert_quit_char);    /* ESC-Q  *//* JJD 3-89 */
  437. X    bind_to_key("^[S",toggle_show_eol_mode);
  438. X    bind_to_key("^[_",dash_to_ul_word);    /* ESC-_  */
  439. X    bind_to_key("^[b",backward_word);    /* ESC-b  */
  440. X    bind_to_key("^[c",capitalize_word);    /* ESC-c  */
  441. X    bind_to_key("^[d",delete_word);    /* ESC-d  */
  442. X    bind_to_key("^[e",toggle_eol_only_mode);    /* ESC-e  *//* JJD 9-86 */
  443. X    bind_to_key("^[f",forward_word);    /* ESC-f  */
  444. X    bind_to_key("^[g",prime_from_file);    /* ESC-g  *//* JJD 9-86 */
  445. X    bind_to_key("^[h",backspace_word);    /* ESC-h  */
  446. X    bind_to_key("^[k",delete_region_to_killbuffer);    /* ESC-k  *//* JJD 3-89 */
  447. X    bind_to_key("^[l",lowercase_word);    /* ESC-l  */
  448. X    bind_to_key("^[m",run_mesg);    /* ESC-m  */
  449. X    bind_to_key("^[o",run_pp);/* ESC-o  *//* JJD 9-86 */
  450. X    bind_to_key("^[p",toggle_pred_mode);    /* ESC-p  *//* JJD 9-86 */
  451. X    bind_to_key("^[q",show_free_nodes);    /* ESC-q  *//* JJD 1-87 */
  452. X    bind_to_key("^[r",run_tty_program);    /* ESC-r  */
  453. X    bind_to_key("^[t",BOGUS);
  454. X    bind_to_key("^[t",run_talk);    /* ESC-t  */
  455. X    bind_to_key("^[u",uppercase_word);    /* ESC-u  */
  456. X    bind_to_key("^[v",show_version);    /* ESC-v  *//* JJD 3-89 */
  457. X    bind_to_key("^[w",run_write);    /* ESC-w  */
  458. X    bind_to_key("^[z",run_ruptime);    /* ESC-z  *//* JJD 2-89 */
  459. X
  460. X    bind_termcap_key("ku",previous_line);    /* ESC-[-A */
  461. X    bind_termcap_key("kd",next_line);    /* ESC-[-B */
  462. X    bind_termcap_key("kl",backward_char);    /* ESC-[-C */
  463. X    bind_termcap_key("kr",forward_char);    /* ESC-[-D */
  464. X}
  465. X
  466. X
  467. Xfile()
  468. X{
  469. X    int             status;
  470. X
  471. X    fd_set readfd;
  472. X    int num;
  473. X    char buf[1024];
  474. X
  475. X    if(!silent){
  476. X        printf("Welcome to the Reactive Keyboard. \r\n");
  477. X        printf("Written at the University of Calgary. \r\n");
  478. X        printf("Version:%s\r\n",VERSION);
  479. X        printf("Please wait until your shell prompt appears (ESC-? for help).\r\n");
  480. X    }
  481. X    init_reactive();    /* MAY TAKE TIME CREATING FREE LIST,     JJD
  482. X                 * 9-86 */
  483. X    signal(SIGCHLD, childdied);
  484. X    signal(SIGSEGV, cleanup);
  485. X    if (pred_mode) make_a_prediction (pred_buff); 
  486. X    while(1){
  487. X        if (pred_mode && pred_buff[0]) {
  488. X            /*
  489. X             * if (pred_mode && !(eol_only_mode &&
  490. X             * *(editor_data.dot))) JJD 9-86
  491. X             */
  492. X            ioctl(pty_master, TIOCGETP, &pty_sgtty);
  493. X            if ((pty_sgtty.sg_flags & ECHO) &&
  494. X                !(pty_sgtty.sg_flags & (RAW | CBREAK)))
  495. X                display_pred_buffer(&editor_data);
  496. X        }
  497. X        FD_ZERO(&readfd);
  498. X        FD_SET(0,&readfd);
  499. X        FD_SET(pty_master,&readfd);
  500. X        if(select(getdtablesize(),&readfd,0,0,0)<0){
  501. X            if( errno == EINTR ){
  502. X                errno = 0;
  503. X                continue;
  504. X            }
  505. X            else
  506. X                perror("Select");
  507. X        }
  508. X        if( FD_ISSET(0,&readfd)){
  509. X            ioctl(pty_master, TIOCGETP, &pty_sgtty);
  510. X            if ((pty_sgtty.sg_flags & ECHO) &&
  511. X              !(pty_sgtty.sg_flags & (RAW | CBREAK))) {
  512. X                num = edit_line(buf);
  513. X            } else
  514. X            num = READ(0, buf, 1024);
  515. X            write(pty_master, buf, num);
  516. X        }
  517. X        if( FD_ISSET(pty_master,&readfd)){
  518. X            if (pred_on_display)
  519. X                erase_pred_buffer(&editor_data);    /* JJD9-86 */
  520. X            erase_current_edit_line (&editor_data);
  521. X            /* JJD: no FILE, keep bigger read size */
  522. X            num = READ(pty_master, buf, 1024);
  523. X            write(1, buf, num);
  524. X        }    
  525. X    }
  526. X}
  527. X
  528. X
  529. Xshutdown_pty_and_tty()
  530. X{
  531. X    close(pty_master);
  532. X    ioctl(0, TIOCSETP, &old_stdin);
  533. X}
  534. X
  535. X
  536. Xint 
  537. Xedit_line(c)
  538. X    char           *c;
  539. X{
  540. X
  541. X    char            ch;
  542. X    int             status, num;
  543. X    fd_set readfd;
  544. X    char            tstring[1024], *cptr;
  545. X    int             count;
  546. X    struct stat     buf;    /* JJD 3-89 was 512 */
  547. X
  548. X    struct ed_buffs *buf_to_use, *cur_line;
  549. X    FILE           *from, *popen();
  550. X
  551. X    status = OK;
  552. X
  553. X    buf_to_use = editor_data.current_ed_buff_ptr;
  554. X    while ((status == OK) || (status == HAVE_CHAR)) {
  555. X        FD_ZERO(&readfd);
  556. X        FD_SET(0,&readfd);
  557. X        FD_SET(pty_master,&readfd);
  558. X        if(select(getdtablesize(),&readfd,0,0,0)<0){
  559. X            if( errno == EINTR ){
  560. X                errno = 0;
  561. X                continue;
  562. X            }
  563. X            else
  564. X                perror("Select");
  565. X        }
  566. X        if( FD_ISSET(0,&readfd)){
  567. X            READ(0, &ch, 1);
  568. X            ch &= 127;    /* Must do this due to parity bit
  569. X                     * over dial-up lines */
  570. X            /* Possibly needed for other lines too.          */
  571. X            editor_data.current_input_char = ch;
  572. X            if (pred_on_display)
  573. X                    erase_pred_buffer(&editor_data);
  574. X                status = keymap[(int) ch][0] (&editor_data);
  575. X            if (pred_mode && ((status == OK) || (status == HAVE_CHAR))) {
  576. X                make_a_prediction(pred_buff);
  577. X                if (pred_buff[0])
  578. X                    display_pred_buffer(&editor_data);
  579. X            }
  580. X        }else{
  581. X            num = READ(pty_master, temp_str, 32);
  582. X            if(num){
  583. X                erase_current_edit_line(&editor_data);
  584. X                write(1, temp_str, num);
  585. X                draw_current_edit_line (&editor_data);
  586. X                if (pred_buff[0]&&pred_mode)
  587. X                    display_pred_buffer(&editor_data);
  588. X            }
  589. X
  590. X        }
  591. X        /* MOVED if (pred_mode... up into if (readfds... above */
  592. X    }
  593. X
  594. X    switch (status) {
  595. X    case FINISHED_EDITING:
  596. X        strcpy(c, editor_data.current_buffer);
  597. X        if ((strlen(c) != 0)) {
  598. X            if (stat(c, &buf) != -1) {    /* if just a directory
  599. X                             * name on command line,
  600. X                             * assume cd  */
  601. X
  602. X                /*
  603. X                 * JJD: this is kind of dicey as is, assumes
  604. X                 * a bit too much about dir names
  605. X                 */
  606. X                /*
  607. X                 * it should check that it is the only thing
  608. X                 * on the line for one thing
  609. X                 */
  610. X
  611. X                if ((buf.st_mode & S_IFMT) == S_IFDIR) {
  612. X                    if (strcmp(".", c) != 0) {    /* JJD 3-89 del . case
  613. X                                     * for ed... */
  614. X                        strcpy(tstring, "cd ");
  615. X                        strcat(tstring, c);
  616. X                        strcpy(c, tstring);
  617. X                    }
  618. X                }
  619. X            }
  620. X        }
  621. X        /*
  622. X         * JJD: to be really useful, this should also know about
  623. X         * pushd and popd
  624. X         */
  625. X
  626. X        if ((strncmp(c, "cd ", 3) == 0) ||
  627. X            (strncmp(c, "chdir ", 6) == 0) ||
  628. X            (strcmp(c, "cd") == 0) ||
  629. X            (strcmp(c, "chdir") == 0)) {
  630. X            if (strncmp(c, "cd ", 3) == 0)
  631. X                cptr = &c[2];    /* JJD 3-89, c[-1]  */
  632. X            else
  633. X                cptr = &c[5];
  634. X            while ((*cptr == ' ') || (*cptr == '\t'))
  635. X                cptr++;
  636. X            if ((*cptr == '\0') ||
  637. X                (strcmp(c, "chdir") == 0) ||
  638. X                (strcmp(c, "cd") == 0))
  639. X                strcpy(tstring, getenv("HOME"));
  640. X            else {
  641. X                tstring[0] = '\0';
  642. X                if (*cptr == '~') {    /* JJD 3-89 added
  643. X                             * abspath, rewrote */
  644. X                    char           *optr = cptr;
  645. X                    if (*(++cptr)) {
  646. X                        while ((*cptr != '\0') && (*cptr != ';'))
  647. X                            cptr++;
  648. X                        *cptr = '\0';
  649. X                        if(myabspath(optr, tstring))
  650. X                            strcpy(tstring,".");
  651. X                            /* we have an error so stay in the current dir */
  652. X                    } else {
  653. X                        strcpy(tstring, getenv("HOME"));
  654. X                    }    /* ... to here */
  655. X                    count = strlen(tstring);
  656. X                } else 
  657. X                    count = 0;
  658. X                for (; (*cptr != '\0') && (*cptr != ';'); cptr++, count++)
  659. X                    tstring[count] = *cptr;
  660. X                tstring[count] = '\0';
  661. X    
  662. X            }
  663. X            chdir(tstring);
  664. X        }
  665. X        strcat(c, "\n");/* JJD 2-89 changed ^M to \n */
  666. X        cur_line = editor_data.current_ed_buff_ptr;
  667. X        cur_line->dot = editor_data.dot;
  668. X        cur_line->mark = editor_data.mark;
  669. X        if (cur_line != buf_to_use) {
  670. X            strcpy(buf_to_use->string, cur_line->string);
  671. X            buf_to_use->dot =
  672. X                &buf_to_use->string[cur_line->dot - cur_line->string];
  673. X            buf_to_use->mark =
  674. X                &buf_to_use->string[cur_line->mark - cur_line->string];
  675. X
  676. X        }
  677. X        if (*(buf_to_use->string)) {
  678. X            editor_data.current_ed_buff_ptr = buf_to_use->next_ptr;
  679. X            editor_data.current_ed_buff_ptr->dot =
  680. X                editor_data.current_ed_buff_ptr->string;
  681. X            editor_data.dot = editor_data.current_ed_buff_ptr->dot;
  682. X            /*
  683. X             * editor_data.current_ed_buff_ptr->mark =
  684. X             * editor_data.current_ed_buff_ptr->string;
  685. X             */
  686. X            editor_data.mark = editor_data.current_ed_buff_ptr->mark;
  687. X            *editor_data.dot = '\0';
  688. X            editor_data.current_buffer = editor_data.dot;
  689. X        } else {
  690. X            editor_data.current_ed_buff_ptr = buf_to_use;
  691. X            editor_data.current_buffer = buf_to_use->string;
  692. X            editor_data.dot = buf_to_use->dot;
  693. X            editor_data.mark = buf_to_use->mark;
  694. X        }
  695. X
  696. X        strcat(c, "");
  697. X        update_the_model(c);    /* JJD 9-86 */
  698. X        if (pred_mode)
  699. X            make_a_prediction(pred_buff);    /* JJD 9-86 */
  700. X        return strlen(c);
  701. X        break;
  702. X
  703. X    case FINISHED_BUT_DONT_ADD_CTRL_M:
  704. X        strcpy(c, editor_data.current_buffer);
  705. X        editor_data.dot = editor_data.current_buffer;
  706. X        editor_data.mark = editor_data.current_buffer;
  707. X        *editor_data.dot = '\0';
  708. X        return (strlen(c));
  709. X        break;
  710. X    }
  711. X    strcpy(c, "");
  712. X    return 0;
  713. X}
  714. X
  715. X
  716. Xint 
  717. Xget_display_length(s)
  718. X    char           *s;
  719. X{
  720. X
  721. X    char           *cptr;
  722. X    int             len;
  723. X
  724. X    cptr = s;
  725. X    len = 0;
  726. X    while (*cptr) {
  727. X        if ((*cptr < 32) || (*cptr == 127))
  728. X            len += 2;
  729. X        else
  730. X            len++;
  731. X        ++cptr;
  732. X    }
  733. X    return len;
  734. X}
  735. X
  736. Xint 
  737. Xget_char_display_length(c)
  738. X    char            c;
  739. X{
  740. X
  741. X    int             len;
  742. X
  743. X    len = 0;
  744. X    if ((c < 32) || (c == 127))
  745. X        len = 2;
  746. X    else
  747. X        len++;
  748. X    return len;
  749. X}
  750. X
  751. Xint 
  752. Xdisplay_string_into_output_string(s)
  753. X    char           *s;
  754. X{
  755. X
  756. X    int             len;
  757. X    char           *cptr;
  758. X
  759. X    cptr = s;
  760. X    len = 0;
  761. X    while (*cptr) {
  762. X        if (*cptr < 32) {
  763. X            len += 2;
  764. X            output_string[output_string_length++] = '^';
  765. X            output_string[output_string_length++] =
  766. X                *cptr++ + '@';
  767. X        } else if (*cptr == 127) {
  768. X            len += 2;
  769. X            output_string[output_string_length++] = '^';
  770. X            output_string[output_string_length++] = '?';
  771. X            ++cptr;
  772. X        } else {
  773. X            len++;
  774. X            output_string[output_string_length++] = *cptr++;
  775. X        }
  776. X    }
  777. X
  778. X    return len;
  779. X}
  780. X
  781. Xint 
  782. Xdisplay_char_into_output_string(c)
  783. X    char            c;
  784. X{
  785. X
  786. X    int             len;
  787. X
  788. X    len = 0;
  789. X    if (c < 32) {
  790. X        len += 2;
  791. X        output_string[output_string_length++] = '^';
  792. X        output_string[output_string_length++] = c + '@';
  793. X    } else if (c == 127) {
  794. X        len += 2;
  795. X        output_string[output_string_length++] = '^';
  796. X        output_string[output_string_length++] = '?';
  797. X    } else {
  798. X        len++;
  799. X        output_string[output_string_length++] = c;
  800. X    }
  801. X
  802. X    return len;
  803. X}
  804. X
  805. Xint 
  806. Xerase_current_edit_line(e)
  807. X    ED_STRUCT      *e;
  808. X{
  809. X
  810. X    int             num_to_erase, count;
  811. X    char           *old_dot;
  812. X
  813. X    /*
  814. X     * added to deal with META-prefixes which turn pred display on...may
  815. X     * not work for all cases
  816. X     */
  817. X    if (pred_on_display)
  818. X        erase_pred_buffer(e);    /* JJD 9-86 */
  819. X    old_dot = e->dot;
  820. X    beginning_of_line(e);
  821. X    e->dot = old_dot;
  822. X    output_string_length = 0;
  823. X
  824. X    num_to_erase = get_display_length(e->current_buffer);
  825. X    for (count = num_to_erase; count; --count)
  826. X        output_string[output_string_length++] = ' ';
  827. X    for (count = num_to_erase; count; --count)
  828. X        tputs(cursor_left, ONE_LINE, append_to_output_string);
  829. X    write(1, output_string, output_string_length);
  830. X
  831. X    return OK;
  832. X}
  833. X
  834. Xint 
  835. Xdraw_current_edit_line(e)
  836. X    ED_STRUCT      *e;
  837. X{
  838. X
  839. X    int             count;
  840. X
  841. X    output_string_length = 0;
  842. X    display_string_into_output_string(e->current_buffer);
  843. X    count = get_display_length(e->dot);
  844. X    for (; count; --count)
  845. X        tputs(cursor_left, ONE_LINE, append_to_output_string);
  846. X    write(1, output_string, output_string_length);
  847. X
  848. X    return OK;
  849. X}
  850. END_OF_FILE
  851. if test 21384 -ne `wc -c <'file+rk.c'`; then
  852.     echo shar: \"'file+rk.c'\" unpacked with wrong size!
  853. fi
  854. # end of 'file+rk.c'
  855. fi
  856. echo shar: End of archive 3 \(of 4\).
  857. cp /dev/null ark3isdone
  858. MISSING=""
  859. for I in 1 2 3 4 ; do
  860.     if test ! -f ark${I}isdone ; then
  861.     MISSING="${MISSING} ${I}"
  862.     fi
  863. done
  864. if test "${MISSING}" = "" ; then
  865.     echo You have unpacked all 4 archives.
  866.     rm -f ark[1-9]isdone
  867. else
  868.     echo You still need to unpack the following archives:
  869.     echo "        " ${MISSING}
  870. fi
  871. ##  End of shell archive.
  872. exit 0
  873.  
  874.